﻿using Abp.Authorization;
using Abp.Domain.Repositories;
using Abp.Runtime.Session;
using Microsoft.EntityFrameworkCore;
using Mt.Site.Core.Authorization;
using Mt.Site.Core.MultiTenancy;
using Mt.Site.Core.Navigations;
using Mt.Site.Core.Navigations.Entities;
using Mt.Site.Core.Navigations.Permissions;
using System;
using System.Linq;
using System.Threading.Tasks;

namespace Mt.Site.Application.Navigation
{
    public class MenuCleanAppService : MtSiteAppServiceBase, IMenuCleanAppService
    {
        private readonly IMenuManager _menuManager;
        private readonly TenantManager _tenantManager;
        private readonly IRepository<RouteSetting, Guid> _routeSettingRepository;

        public MenuCleanAppService(
            IMenuManager menuManager, 
            TenantManager tenantManager,
            IRepository<RouteSetting, Guid> routeSettingRepository)
        {
            _menuManager = menuManager;
            _tenantManager = tenantManager;
            _routeSettingRepository = routeSettingRepository;
        }

        [AbpAuthorize(MenuPermissions.Pages_Tenant_Menus_CleanData)]
        public async Task<int> CleanMenus()
        {
            var tenantId = AbpSession.GetTenantId();
            return await CleanMenusByTenantId(tenantId);
        }

        [AbpAuthorize]
        private async Task<int> CleanMenusByTenantId(int tenantId)
        {
            return await _menuManager.CleanMenus(tenantId);
        }

        [AbpAuthorize(MenuPermissions.Pages_Administration_CleanMenuDataForAllTenant)]
        public async Task<int> CleanMenusByHost()
        {
            var tenantIds = await (from tenant in _tenantManager.Tenants
                                   where tenant.IsActive
                                   select tenant.Id).ToListAsync();
            int sum = 0;
            foreach (var tenantId in tenantIds)
            {
                sum += await CleanMenusByTenantId(tenantId);
            }
            return sum;
        }

        [AbpAuthorize(MenuPermissions.Pages_Tenant_Menus_ResetUnitCode)]
        public async Task ResetCode()
        {
            var tenantId = AbpSession.GetTenantId();
            await _menuManager.ReSetCode(tenantId);
        }

        [AbpAuthorize(MenuPermissions.Pages_Administration_ResetMenuItemCodeForAllTenant)]
        public async Task ResetCodeByHost()
        {
            var tenantIds = await (from tenant in _tenantManager.Tenants
                                   where tenant.IsActive
                                   select tenant.Id).ToListAsync();
            foreach (var tenantId in tenantIds)
            {
                await _menuManager.ReSetCode(tenantId);
                await CurrentUnitOfWork.SaveChangesAsync();
            }
        }
        #region 缓存

        [AbpAuthorize(
            MenuPermissions.Pages_Tenant_Menus, 
            MenuPermissions.Pages_Administration_BackendPage_Create,
            MenuPermissions.Pages_Administration_BackendPage_Edit,
            RequireAllPermissions = false)]
        public async Task ResetMenuCache()
        {
            await _menuManager.ResetMenuCacheAsync(AbpSession.GetTenantId());
        }

        [AbpAuthorize(
            AppPermissions.Pages_Administration_Host_Maintenance,
            MenuPermissions.Pages_Administration_BackendPage_Create,
            MenuPermissions.Pages_Administration_BackendPage_Edit, 
            RequireAllPermissions = false)]
        public async Task ResetMenuCacheByHost()
        {
            var tenantIds = await (from tenant in _tenantManager.Tenants
                                   where tenant.IsActive
                                   select tenant.Id).ToListAsync();

            await _menuManager.ResetMenuCacheAsync(tenantIds);
        }

        [AbpAuthorize(AppPermissions.Pages_Administration_Host_Maintenance, MenuPermissions.Pages_Tenant_Menus, RequireAllPermissions = false)]
        public async Task ResetCustomRouteCache()
        {
            if (AbpSession.TenantId == null)
            {
                var tenants = await (from tenant in _tenantManager.Tenants
                                       where tenant.IsActive
                                       select new { tenant .Id, tenant.Name}).ToListAsync();
                foreach (var item in tenants)
                {
                    await _menuManager.ResetCustomRouteCache(item.Name, item.Id);
                }
            }
            else
            {
                var tenants = await (from tenant in _tenantManager.Tenants
                                     where tenant.IsActive && tenant.Id == AbpSession.TenantId.Value
                                     select new { tenant.Id, tenant.Name }).ToListAsync();
                foreach (var item in tenants)
                {
                    await _menuManager.ResetCustomRouteCache(item.Name, item.Id);
                }
            }
        }


        #endregion

        [AbpAuthorize(MenuPermissions.Pages_Administration_CleanMenuDataForAllTenant)]
        public int CleanRouter()
        {
            using (CurrentUnitOfWork.DisableFilter(MtSiteConsts.AbpDataFilters.MustHaveLanguage))
            {
                var query =
                        from data in (
                        from router in _routeSettingRepository.GetAll()
                        group 1
                        by new { router.Language, router.RelatedId } into g
                        select new
                        {
                            RelateId = g.Key.RelatedId,
                            Language = g.Key.Language,
                            Count = g.Count()
                        })
                        where data.Count > 1
                        select new
                        {
                            RelteId1 = data.RelateId,
                            Language1 = data.Language
                        };
                var list = query.ToList();

                foreach (var item in list)
                {
                    var list1 = _routeSettingRepository.GetAllList(n => n.Language == item.Language1 && item.RelteId1 == n.RelatedId);
                    list1 = list1.OrderByDescending(m => m.LastModificationTime)
                                 .ThenByDescending(m => m.CreationTime)
                                 .ToList();
                    for (int i = 1, len = list1.Count; i < len; i++)
                    {
                        _routeSettingRepository.Delete(list1[i]);
                    }
                }
                return list.Count;
            }
        }

    }
}
